package edu.pku.sei.transformation.editor.model;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;

import edu.pku.sei.modeler.model.core.MetaModel;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.transformation.editor.internal.TransformationEditorModelRoot;
import edu.pku.sei.transformation.editor.model.base.TypedElement;
import edu.pku.sei.transformation.editor.model.constraint.ConstraintConnection;
import edu.pku.sei.transformation.editor.model.constraint.IConstrainableElement;

public class ModelType extends TypedElement implements IConstrainableElement {
	private ArrayList<ConstraintConnection> constraintConnections = new ArrayList<ConstraintConnection>();
	private ArrayList<Compatiable> incomings = new ArrayList<Compatiable>();
	private ArrayList<Compatiable> outgoings = new ArrayList<Compatiable>();

	@Override
	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeNodes(root,
				ModelPackage.MODELTYPE_OUTGOING_COMPETIABLE, outgoings);
		XMLUtility.xmlInstance.serializeNodesNotContain(root,
				ModelPackage.MODELTYPE_INCOMING_COMPETIABLE, incomings);
		XMLUtility.xmlInstance.serializeNodes(root,
				ModelPackage.CONSTRAINT_CONNECTION, constraintConnections);

	}

	@Override
	public void deSerialize(Element root) {
		super.deSerialize(root);
		this.incomings.addAll(XMLUtility.xmlInstance
				.deSerializeNodesNotContain(root,
						ModelPackage.MODELTYPE_INCOMING_COMPETIABLE, this));
		this.outgoings.addAll(XMLUtility.xmlInstance.deSerializeNodes(root,
				ModelPackage.MODELTYPE_OUTGOING_COMPETIABLE));
		this.constraintConnections.addAll(XMLUtility.xmlInstance
				.deSerializeNodes(root, ModelPackage.CONSTRAINT_CONNECTION));
	}

	@Override
	public void dynamicSet(String featureID, Object value) {
		if (ModelPackage.MODELTYPE_INCOMING_COMPETIABLE.endsWith(featureID)) {
			this.incomings.add((Compatiable) value);
		} else {
			super.dynamicSet(featureID, value);
		}
	}

	@Override
	public List<ConstraintConnection> getConstraintConnections() {
		return constraintConnections;
	}

	public List<Compatiable> getIncomingCompatiables() {
		return this.incomings;
	}

	public List<Compatiable> getOutgoingCompatiables() {
		return this.outgoings;
	}

	public List getAllTypes() {
		if (this.type instanceof MetaModel) {
			return ((MetaModel) this.type).getAllTypes();
		} else {
			return new ArrayList();
		}
	}

	@Override
	public Object[] getTypes() {
		return TransformationEditorModelRoot.getMetaModelPkg(getModel())
				.getNamedElements().toArray();
	}
	
	public edu.pku.sei.transformation.editor.model.MetaModel getMetaModel() {
		return (edu.pku.sei.transformation.editor.model.MetaModel)getType();
	}
	
	public boolean isCompatible(ModelType type) {
		if (this == type)
			return true;
		for (Compatiable compatible : this.incomings) {
			ModelType temp = compatible.getSource();
			if (temp == type || temp.isCompatible(type))
				return true;
		}
		return false;
	}
}
